package com.ygxsk.carhome.retrofit;

import android.net.ParseException;
import android.text.TextUtils;

import com.blankj.utilcode.util.LogUtils;
import com.blankj.utilcode.util.ObjectUtils;
import com.blankj.utilcode.util.Utils;
import com.ygxsk.carhome.constant.ConstantApi;
import com.ygxsk.carhome.constant.ConstantSign;
import com.ygxsk.carhome.utils.CommUtils;
import com.ygxsk.integrated.retrofit.Parameterkey;

import org.jetbrains.annotations.NotNull;
import org.json.JSONException;

import java.net.ConnectException;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.util.HashMap;

import io.reactivex.rxjava3.functions.Consumer;

public abstract class ErrorConsumer implements Consumer<Throwable> {

    //2022年11月6日16:23:47 我自己自定义的以3xxx为开头的；
    public static final String UNKNOWN = "30000";
    //int格式的做判断
    public static final Integer UNKNOWN_INT = 30000;
    //{"data":"","message":"当前签署任务状态不允许撤销","code":"29999"}
    public static final Integer FILE_SIGNATRUE_INT_29999 = 29999;
    public static final String PARSE_ERROR = "30001";
    public static final String NETWORK_ERROR = "30002";

    @Override
    public void accept(@NotNull Throwable throwable) throws Exception {

        //对异常进行处理
        if (!ObjectUtils.isEmpty(throwable)) {

            ApiException apiExceptionCurrent = null;

            if (throwable instanceof ApiException) {//这里是项目之中人为自定义的处理非2W的数据异常，在主界面做提示用。

                //=============================================================================================================
                //走到这里是主线程。
                //LogUtils.d(ConstantSign.LOGCAT_NOMAL + "是(instanceof ApiException)" + //

                LogUtils.d(ConstantSign.LOGCAT_NOMAL + "是(ApiException)" + //
                        throwable.getClass().getName().toString() + //
                        "--code=>" + ((ApiException) throwable).getDisplayCode() +//
                        "--message=>" + ((ApiException) throwable).getDisplayMessage());//

                //2022年11月6日16:51:54 打印是在主线程；
                //    itchen-->是(ApiException)com.ygxsk.integrated.retrofit.ApiException--code=>null--message=>null
                //main, com.dgj.propertysmart.retrofit.ErrorConsumer.accept(ErrorConsumer.java:39)
                //itchen->是(instanceof ApiException)com.dgj.propertysmart.retrofit.ApiException--code=>20002--message=>无数据--getLocalizedMessage==>null

                apiExceptionCurrent = (ApiException) throwable;

                if (!ObjectUtils.isEmpty(apiExceptionCurrent)) {

                    //2022年11月5日21:34:43这里逻辑能走到这里 在observable.error之中【子线程之中上传日志】我处理过了，此处再上传就出现重复日志；
                    //非20000的数据都在这里处理
                    //-----------------------------------------------------------------------------------------------------
                    if (apiExceptionCurrent.getApiRequestSubListener() != null) {

                        //-------------------------------------------------------------------------------------------------
                        //-----------------------------------------------------------------------------------------------------
                        //bug：如果是接口是【上传日志】接口，那么就不处理这个弹窗，因为日志报错401干扰了正常的【token失效】；
                        if (apiExceptionCurrent.getAddLogUpLoadInfo().getWhat() != ConstantApi.WHAT_ADDLOG) {

                            //正常处理【非20000】的数据
                            apiExceptionCurrent.getApiRequestSubListener().onErrorServerNotSuccessDataResponse(//
                                    apiExceptionCurrent.getAddLogUpLoadInfo().getWhat(),//
                                    apiExceptionCurrent.getAddLogUpLoadInfo().isToastToUser(),//
                                    apiExceptionCurrent.getAddLogUpLoadInfo().getActivity(),//
                                    apiExceptionCurrent.getDisplayCode(),//非20000的弹窗
                                    apiExceptionCurrent.getDisplayMessage());//非20000的提示

                        }

                        //-----------------------------------------------------------------------------------------------------
                        //在处理【非20000】之后 处理一些自己的个性化数据-放在界面正常的处理之后，单独处理，
                        //2023-5-18 10:17:03 如果是【上传日志本身的接口，那么就不再添加-上传日志接口】
                        if (apiExceptionCurrent.getAddLogUpLoadInfo().getWhat() != ConstantApi.WHAT_ADDLOG) {

                            apiExceptionCurrent.getApiRequestSubListener().handlerSomeThingNotSuccessDataForItSelf(//
                                    apiExceptionCurrent.getAddLogUpLoadInfo().getWhat(),//
                                    apiExceptionCurrent.getDisplayCode(),//非20000的弹窗
                                    apiExceptionCurrent.getDisplayMessage());//非20000的提示

                        }

                        //-------------------------------------------------------------------------------------------------
                    }
                    //-----------------------------------------------------------------------------------------------------

                    //如果是10000开头的通知编号，就提示
                    if (!TextUtils.isEmpty(apiExceptionCurrent.getDisplayCode())) {

                        int code = Integer.parseInt(apiExceptionCurrent.getDisplayCode());
                        LogUtils.d(ConstantSign.LOGCAT_NOMAL + "当前报错的错误码是-code->" + code);
                        //{"data":"","message":"喷涂房与预约场地不一致","code":"21413"}

                        if (code > FILE_SIGNATRUE_INT_29999 || code <= ConstantApi.RESPONSE_19999) {

                            //2023年10月28日11:53:09 处理10000开头的报错信息给用户
                            //调用error方法
                            error(apiExceptionCurrent);

                        }

                        //其他的需要特殊处理的
                    }


                }
//                else {
//                    LogUtils.d(ConstantApi.LOGCAT_NOMAL + "-(ApiException) throwable-exception是空值~");
//                }

                //=============================================================================================================

            } else {

                //=============================================================================================================

                //非ApiException类的报错日志 例如：NullPointerException
                //java.lang.ClassCastException: java.lang.NullPointerException cannot be cast to com.dgj.propertysmart.retrofit.ApiException

                LogUtils.d(ConstantSign.LOGCAT_NOMAL + "非ApiException报错->" + throwable.getClass().getName().toString() +//
                        "--getLocalizedMessage2==>" + throwable.getLocalizedMessage());//

                //itchen->java.lang.NullPointerException--accept2==>
                // Attempt to invoke virtual method 'void android.app.Activity.runOnUiThread(java.lang.Runnable)'
                // on a null object reference

                //---------------------------------------------------------------------
                //等给消息体 确定之后 那么就可以直接上传日志了
                //Exception exceptionOtherReson = throwable;

                if (throwable instanceof JSONException//
                        || throwable instanceof ParseException) {//

                    //解析错误
                    ApiException exceptionOtherReson = new ApiException(PARSE_ERROR, throwable.getMessage());
                    methodErrorMyThrowable(exceptionOtherReson);

                } else if (throwable instanceof ConnectException) {
                    //网络错误
                    ApiException exceptionOtherReson = new ApiException(NETWORK_ERROR, throwable.getMessage());
                    methodErrorMyThrowable(exceptionOtherReson);

                } else if (throwable instanceof UnknownHostException //
                        || throwable instanceof SocketTimeoutException) {//
                    //连接错误
                    ApiException exceptionOtherReson = new ApiException(NETWORK_ERROR, throwable.getMessage());
                    methodErrorMyThrowable(exceptionOtherReson);

                } else {
                    //未知错误
                    ApiException exceptionOtherReson = new ApiException(UNKNOWN, throwable.getMessage());
                    methodErrorMyThrowable(exceptionOtherReson);
                }

                //=============================================================================================================================

            }

        }
//        else {
//            //【是意外的日志】
//            LogUtils.d(ConstantApi.LOGCAT_NOMAL + "Not ApiException--accept==>" + "throwable-是空值");
//        }

    }

    //使用时实现error方法即可。
    protected abstract void error(ApiException apiException);

    /**
     * 单独额外的处理 非 ApiException 类的报错
     */
    private void methodErrorMyThrowable(ApiException exceptionOtherReson) {

        //可能需要剪切走的代码
        if (!ObjectUtils.isEmpty(exceptionOtherReson)) {

//            LogUtils.d(ConstantApi.LOGCAT_NOMAL + "调用 error((ApiException) exceptionOtherReson) 之前");
            //调用error方法
            error(exceptionOtherReson);

//            LogUtils.d(ConstantApi.LOGCAT_NOMAL + "调用 error((ApiException) exceptionOtherReson) 之后");

            //因为这里频繁上传日志
//            if (MMKV.defaultMMKV().decodeBool(ConstantSign.MMKV_ADDLOG_SUCCESSED)) {
            // : 2022-11-06 这种其他原因的,请求数据Request的报错-暂时只给提示.
            HashMap<String, Object> hashMapAddLog = new HashMap<>();
            hashMapAddLog.put(Parameterkey.addLogCode, exceptionOtherReson.getDisplayCode());
            //hashMapAddLog.put("addLogMessage", exceptionOtherReson.getDisplayMessage());//重复添加 造成addlog上传压力
            //hashMapAddLog.put("addLogMessage", exceptionOtherReson.getDisplayMessage());

            //这种报错是程序的报错，是可以上传的【是意外的日志】.
            new ApiRequestSubListener<Throwable>() {
            }.addLogInApiRequestListener(
                    Utils.getApp(),//
                    ConstantSign.ERROR_CUSTOMER_MYTHROWABLE,//ApiService.getSysOperLogUrl
                    ConstantSign.REQUEST_METHOD_POST,//
                    hashMapAddLog,//
                    CommUtils.addLogFormatException(exceptionOtherReson));
//            }

        }
//        else {
//
//            //【是意外的日志】
//            LogUtils.d(ConstantApi.LOGCAT_NOMAL + "-ApiException.handleException(throwable)-exception是空值~");
//
//        }

    }
}
